﻿using Abp.Application.Services.Dto;
using Batman.Cms.Core.Models.Commands;
using Batman.Cms.Core.Utils;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;

namespace Batman.Cms.Core.Commands
{
    public static class CommandPool
    {
        private static string MapPath { get; set; }

        private static List<Statement> Maps { get; set; } = new List<Statement>();

        private static void LoadMaps()
        {
            if (!Directory.Exists(MapPath)) return;
            if (Maps.Count > 0) return;

            Maps = LoadStatements();
        }

        private static List<Statement> LoadStatements()
        {
            var files = Directory.GetFiles(MapPath, "*", SearchOption.AllDirectories);
            var results = new List<Statement>();

            foreach (var file in files)
            {
                var bytes = File.ReadAllBytes(file);
                var statements = XmlUtil.Deserialize<List<Statement>>(bytes);

                if (statements.Count > 0) results.AddRange(statements);
            }

            results.ForEach(t => Minifier(t));
            return results;
        }

        // 处理多余的空格和回车
        private static void Minifier(Statement statement)
        {
            if (statement == null || statement.Content == null) return;

            var content = statement.Content;

            var matches = Regex.Matches(content, @"'(.*)?'");
            var temporaries = new List<NameValueDto<string>>();

            for (int i = 0; i < matches.Count; i++)
            {
                var match = matches[i];
                var key = "$" + i.ToString();
                var value = match.Groups[0].Value;
                content = content.Replace(value, key);
                temporaries.Add(new NameValueDto<string>(key, value));
            }

            var newStr = Regex.Replace(content, @"\s+", " ");

            temporaries.ForEach(t => newStr = newStr.Replace(t.Name, t.Value));

            statement.Content = newStr.Trim();
        }

        public static string GetSQL(string key)
        {
            var found = Maps.Where(t => t.Name == key).FirstOrDefault();
            if (found == null) return null;

            return found.Content;
        }

        public static void AddCommandPoolService(this IServiceCollection services, Action<CommandPoolOptions> optionsAction)
        {
            var options = new CommandPoolOptions();

            optionsAction(options); // 设置路径

            if (string.IsNullOrEmpty(options.DirectoryFullPath))
            {
                var env = services.BuildServiceProvider().GetService<IHostingEnvironment>();

                // 默认在根目录下，因为在APP_DATA下可能有读权限问题
                MapPath = Path.Combine(env.ContentRootPath, "Maps");
            }
            else
            {
                MapPath = Path.Combine(options.DirectoryFullPath);
            }
            if (!Directory.Exists(MapPath)) Directory.CreateDirectory(MapPath);

            LoadMaps();
        }
    }

    public class CommandPoolOptions
    {
        public string DirectoryFullPath { get; set; }
    }
}
